#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;
const int maxn=300;

bool map[maxn+2][maxn+2];
int node[maxn+2][maxn+2], h[maxn+2][maxn+2], v[maxn+2][maxn+2], hv[maxn+2][maxn+2], emp[maxn+2][maxn+2][maxn+2], col[maxn+2][maxn+2], n, m;

int addUp(int x, int y, int a[][maxn+2], int t) {
    return a[x][y] = a[x-1][y]+a[x][y-1]-a[x-1][y-1]+t;
}

int get(int a[][maxn+2], int x1, int y1, int x2, int y2) {
    if (x2<x1 || y2<y1) return 0;
    else return a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1];
}

void mark(int x, int y, bool typ, int c, int &x1, int &y1, int &x2, int &y2) {
    const static int dir[4][2]={{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
    col[x][y] = c;
    x1 = min(x1, x), x2 = max(x2, x);
    y1 = min(y1, y), y2 = max(y2, y);
    for (int i=0; i<4; i++) {
        int nx=x+dir[i][0], ny=y+dir[i][1];
        if (nx && ny && nx<=n && ny<=m && map[nx][ny]==typ && col[nx][ny]!=c) {
            mark(nx, ny, typ, c, x1, y1, x2, y2);
        }
    }
}

void initHV() {
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m+1; j++) {
            addUp(i, j, node, map[i][j]);
            addUp(i, j, h, map[i][j] && map[i-1][j]);
            addUp(i, j, v, map[i][j] && map[i][j-1]);
            addUp(i, j, hv, map[i][j] && map[i-1][j] && map[i][j-1] && map[i-1][j-1]);
        }
    }
}

void initEmpty() {
    int ver=0;
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m; j++) {
            if (!map[i][j] && !col[i][j]) {
                int x1=i, x2=i, y1=j, y2=j;
                mark(i, j, 0, ++ver, x1, y1, x2, y2);
                emp[x1-1][x2+1][y2+1] = max(emp[x1-1][x2+1][y2+1], y1-1);
            }
        }
    }

    for (int l=1; l<=n; l++) {
        for (int i=1; i+l<=n; i++) {
            int j = i+l;
            for (int k=1; k<=m; k++) {
                emp[i][j][k] = max(emp[i][j][k], max(emp[i+1][j][k], emp[i][j-1][k]));
            }
        }
    }
}

int& update(int t, int a[], int ver[], int ve) {
    if (ver[t]!=ve) {
        ver[t]=ve;
        a[t] = 0;
    }
    return a[t];
}

ll solve(int x1, int x2) {
    static int cnt[2*maxn*maxn+1], ver[2*maxn*maxn+1], ve;
    ll ans=0;
    ve++;
    update(maxn*maxn, cnt, ver, ve) = 1;
    for (int l=0, r=1; r<=m; r++) {
        int t;
        for (; l<emp[x1][x2][r]; l++) {
            t=get(node, x1, 1, x2, l)-get(h, x1+1, 1, x2, l)-get(v, x1, 2, x2, l+1)+get(hv, x1+1, 2, x2, l+1);
            if (ver[maxn*maxn+t]!=ve) printf("Err!\n");
            cnt[maxn*maxn+t]--;
        }
        t=get(node, x1, 1, x2, r)-get(h, x1+1, 1, x2, r)-get(v, x1, 2, x2, r)+get(hv, x1+1, 2, x2, r);
        ans += update(maxn*maxn+t-1, cnt, ver, ve);
        t=get(node, x1, 1, x2, r)-get(h, x1+1, 1, x2, r)-get(v, x1, 2, x2, r+1)+get(hv, x1+1, 2, x2, r+1);
        update(maxn*maxn+t, cnt, ver, ve)++;
    }
    return ans;
}

int main() {
    freopen("village.in", "r", stdin);
    freopen("village.out", "w", stdout);

    scanf("%d %d", &n, &m);
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m; j++) {
            int t;
            scanf("%1d", &t);
            map[i][j] = t;
        }
    }

    initHV();
    initEmpty();

    ll ans=0;
    for (int i=1; i<=n; i++) {
        for (int j=i; j<=n; j++) {
            ans += solve(i, j);
        }
    }
    printf("%lld\n", ans);

    fclose(stdin);
    fclose(stdout);
    return 0;
}
